using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Sponsorship.Domain;
using Sponsorship.ReadModel;
using StructureMap;

namespace Sponsorship.Infrastructure.BootStrapping
{
    /// <summary>
    /// Registers all domain event handlers for the respective domain events in the <see cref="IBus"/> set up by the <see cref="BootStrapper"/>.
    /// </summary>
    public class EventRoutesRegistrar
    {
        private static readonly MethodInfo _registerMethod = typeof(EventRoutesRegistrar).GetMethod("RegisterRoutes");

        private readonly IBus _messageRouter;
        
        public EventRoutesRegistrar(IBus messageRouter)
        {
            _messageRouter = messageRouter;
        }

        public void RegisterRoutesForAllEvents()
        {
            var eventTypes = GetEventTypes();
            foreach (var eventType in eventTypes)
                _registerMethod.MakeGenericMethod(eventType).Invoke(this, null);
        }

        public void RegisterRoutes<T>() where T : IEvent
        {
            var eventHandlers = ObjectFactory.GetAllInstances<IEventHandler<T>>();
            foreach (var eventHandler in eventHandlers)
                _messageRouter.RegisterHandler<T> (eventHandler.Handle);
        }

        private IEnumerable<Type> GetEventTypes()
        {
            return typeof(IEvent)
                .Assembly
                .GetExportedTypes()
                .Where(x => x.GetInterface(typeof(IEvent).Name) == typeof(IEvent))
                .ToList();
        }
    }
}